package utn.frba.matematicasuperior.modelo;

import java.util.List;
import java.util.ListIterator;

import utn.frba.matematicasuperior.utiles.Orden;

public class PolinomioInterpolante {

	private static final String TITULO_PROGRESIVA = "Polinomio interpolante con diferencias finitas progresivas ";
	private static final String TITULO_REGRESIVA = "Polinomio interpolante con diferencias finitas regresivas ";

	/************************************************************/
	/************************ ATRIBUTOS *************************/
	/************************************************************/

	private Integer grado;
	private String expresionProgresiva;
	private String expresionRegresiva;
	private List<Double> coeficientes;
	private Soporte soporteAsociado;

	/************************************************************/
	/*********************** PROPIEDADES ************************/
	/************************************************************/

	public Integer getGrado() {
		return grado;
	}

	public void setGrado(Integer grado) {
		this.grado = grado;
	}

	public String getExpresionRegresiva() {
		return expresionRegresiva;
	}

	public void setExpresionRegresiva(String expresionRegresiva) {
		this.expresionRegresiva = expresionRegresiva;
	}

	public String getExpresionProgresiva() {
		return expresionProgresiva;
	}

	public void setExpresionProgresiva(String expresion) {
		this.expresionProgresiva = expresion;
	}

	public List<Double> getCoeficientes() {
		return coeficientes;
	}

	public void setCoeficientes(List<Double> coeficientes) {
		this.coeficientes = coeficientes;
	}

	public Soporte getSoporteAsociado() {
		return soporteAsociado;
	}

	public void setSoporteAsociado(Soporte soporteAsociado) {
		this.soporteAsociado = soporteAsociado;
	}

	/************************************************************/
	/*********************** CONSTRUCTOR ************************/
	/************************************************************/

	public PolinomioInterpolante() {
	}

	/************************************************************/
	/******************** METODOS PUBLICOS **********************/
	/************************************************************/

	/************************************************************/
	/******************** METODOS PRIVADOS **********************/
	/************************************************************/

	public String resolverGradoPolinomio() {

		for (Orden orden : this.soporteAsociado.getDiferenciaFinita()
				.getOrdenes()) {
			if (!orden.esOrdenNula()) {
				grado = orden.getNroOrden();
			}
		}

		return String.valueOf(grado);

	}

	public String resolverExpresion() {

		List<Double> coeficientesProgresivos = this.getSoporteAsociado()
				.obtenerDiferenciaFinitaProgresiva();

		String polinomioProgresivo = armarPolinomioProgresivo(coeficientesProgresivos);

		expresionProgresiva = TITULO_PROGRESIVA + "\n" + polinomioProgresivo
				+ "\n";

		List<Double> coeficientesRegresivos = this.getSoporteAsociado()
				.obtenerDiferenciaFinitaRegresiva();

		String polinomioRegresivo = armarPolinomioRegresivo(coeficientesRegresivos);

		expresionRegresiva = TITULO_REGRESIVA + "\n" + polinomioRegresivo
				+ "\n";

		return expresionProgresiva + expresionRegresiva;
	}

	private String armarPolinomioRegresivo(List<Double> coeficientesRegresivos) {

		String polinomioRegresivo = "P(x) = " + coeficientesRegresivos.get(0);

		ListIterator<Double> itAbcisas = this.soporteAsociado.obtenerAbcisas()
				.listIterator(this.soporteAsociado.obtenerAbcisas().size());

		ListIterator<Double> itCoeficientes = coeficientesRegresivos
				.listIterator(1);

		String raices = "";

		while (itAbcisas.hasPrevious() && itCoeficientes.hasNext()) {
			Double abcisa = itAbcisas.previous();
			Double coeficiente = itCoeficientes.next();

			if (coeficiente != 0.0) {
				if (coeficiente > 0.0) {
					String nuevaRaiz = "";
					if (abcisa > 0) {
						nuevaRaiz = "(x-" + abcisa + ")";
						raices = raices + nuevaRaiz;

						polinomioRegresivo = polinomioRegresivo + " + "
								+ coeficiente + raices;
					} else {
						nuevaRaiz = "(x+" + abcisa + ")";
						raices = raices + nuevaRaiz;

						polinomioRegresivo = polinomioRegresivo + " + "
								+ coeficiente + raices;
					}
				} else {
					coeficiente = Math.abs(coeficiente);
					String nuevaRaiz = "";
					if (abcisa > 0) {
						nuevaRaiz = "(x-" + abcisa + ")";
						raices = raices + nuevaRaiz;

						polinomioRegresivo = polinomioRegresivo + " - "
								+ coeficiente + raices;
					} else {
						nuevaRaiz = "(x+" + abcisa + ")";
						raices = raices + nuevaRaiz;

						polinomioRegresivo = polinomioRegresivo + " - "
								+ coeficiente + raices;
					}
				}
			}
		}

		return polinomioRegresivo;

	}

	private String armarPolinomioProgresivo(List<Double> coeficientesProgresivos) {

		String polinomioProgresivo = "P(x) = " + coeficientesProgresivos.get(0);

		ListIterator<Double> itAbcisas = this.soporteAsociado.obtenerAbcisas()
				.listIterator();

		ListIterator<Double> itCoeficientes = coeficientesProgresivos
				.listIterator(1);

		String raices = "";

		while (itAbcisas.hasNext() && itCoeficientes.hasNext()) {
			Double abcisa = itAbcisas.next();
			Double coeficiente = itCoeficientes.next();

			if (coeficiente != 0.0) {
				if (coeficiente > 0.0) {
					String nuevaRaiz = "";
					if (abcisa >= 0.0) {
						nuevaRaiz = "(x-" + abcisa + ")";
						raices = raices + nuevaRaiz;

						polinomioProgresivo = polinomioProgresivo + " + "
								+ coeficiente + raices;
					} else {
						nuevaRaiz = "(x+" + Math.abs(abcisa) + ")";
						raices = raices + nuevaRaiz;

						polinomioProgresivo = polinomioProgresivo + " + "
								+ coeficiente + raices;
					}
				} else {
					coeficiente = Math.abs(coeficiente);
					String nuevaRaiz = "";
					if (abcisa >= 0.0) {
						nuevaRaiz = "(x-" + abcisa + ")";
						raices = raices + nuevaRaiz;

						polinomioProgresivo = polinomioProgresivo + " - "
								+ coeficiente + raices;
					} else {
						nuevaRaiz = "(x+" + Math.abs(abcisa) + ")";
						raices = raices + nuevaRaiz;

						polinomioProgresivo = polinomioProgresivo + " - "
								+ coeficiente + raices;
					}
				}
			}
		}
		return polinomioProgresivo;
	}

	public Double evaluarPolinomio(Double x) {

		Double resultado = null;

		ListIterator<Double> itCoeficientes = this.getSoporteAsociado()
				.obtenerDiferenciaFinitaProgresiva().listIterator(1);

		ListIterator<Double> itAbcisas = this.getSoporteAsociado()
				.obtenerAbcisas().listIterator();

		resultado = this.getSoporteAsociado()
				.obtenerDiferenciaFinitaProgresiva().get(0);

		Double raizAcumulada = 1.0;

		while (itCoeficientes.hasNext() && itAbcisas.hasNext()) {

			Double abcisa = itAbcisas.next();
			Double coeficiente = itCoeficientes.next();
			Double nuevaRaiz = x - abcisa;
			raizAcumulada = raizAcumulada * nuevaRaiz;
			resultado = resultado + coeficiente * raizAcumulada;

		}

		return resultado;

	}
}
